const User = require('../models/User');
const { asyncHandler } = require('../middleware/errorMiddleware');
const { generateToken, generateRefreshToken, verifyRefreshToken } = require('../middleware/authMiddleware');
const { cache } = require('../config/database');
const logger = require('../utils/logger');
const crypto = require('crypto');

// @desc    注册用户
// @route   POST /api/auth/register
// @access  Public
const register = asyncHandler(async (req, res) => {
  const { username, email, password } = req.body;

  try {
    // 创建用户
    const user = await User.create({
      username,
      email,
      password
    });

    // 生成token
    const token = generateToken(user.id);
    const refreshToken = generateRefreshToken(user.id);

    // 记录日志
    logger.info(`New user registered: ${user.email}`);

    res.status(201).json({
      success: true,
      data: {
        user: user.toJSON(),
        token,
        refreshToken
      },
      message: 'User registered successfully'
    });
  } catch (error) {
    logger.error('Registration error:', error);
    res.status(400);
    throw new Error(error.message);
  }
});

// @desc    用户登录
// @route   POST /api/auth/login
// @access  Public
const login = asyncHandler(async (req, res) => {
  const { email, password } = req.body;

  try {
    // 查找用户（包含密码）
    const userWithPassword = await User.findByEmailWithPassword(email);

    if (!userWithPassword) {
      res.status(401);
      throw new Error('Invalid email or password');
    }

    // 检查用户状态
    if (userWithPassword.status !== 'active') {
      res.status(401);
      throw new Error('Account is not active');
    }

    // 验证密码
    const isPasswordValid = await User.validatePassword(password, userWithPassword.password);

    if (!isPasswordValid) {
      res.status(401);
      throw new Error('Invalid email or password');
    }

    // 创建用户对象（不包含密码）
    const user = await User.findById(userWithPassword.id);

    // 更新最后登录时间
    await user.updateLastLogin();

    // 生成token
    const token = generateToken(user.id);
    const refreshToken = generateRefreshToken(user.id);

    // 记录登录日志
    logger.info(`User logged in: ${user.email}`);

    res.json({
      success: true,
      data: {
        user: user.toJSON(),
        token,
        refreshToken
      },
      message: 'Login successful'
    });
  } catch (error) {
    logger.error('Login error:', error);
    throw error;
  }
});

// @desc    刷新token
// @route   POST /api/auth/refresh
// @access  Public
const refreshToken = asyncHandler(async (req, res) => {
  const { refreshToken } = req.body;

  if (!refreshToken) {
    res.status(401);
    throw new Error('Refresh token is required');
  }

  try {
    // 验证刷新token
    const decoded = verifyRefreshToken(refreshToken);

    // 检查用户是否存在且活跃
    const user = await User.findById(decoded.id);
    if (!user || user.status !== 'active') {
      res.status(401);
      throw new Error('Invalid refresh token');
    }

    // 生成新的token
    const newToken = generateToken(user.id);
    const newRefreshToken = generateRefreshToken(user.id);

    res.json({
      success: true,
      data: {
        token: newToken,
        refreshToken: newRefreshToken
      },
      message: 'Token refreshed successfully'
    });
  } catch (error) {
    logger.error('Token refresh error:', error);
    res.status(401);
    throw new Error('Invalid refresh token');
  }
});

// @desc    用户登出
// @route   POST /api/auth/logout
// @access  Private
const logout = asyncHandler(async (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];

  if (token) {
    // 将token添加到黑名单
    const tokenExpiry = 30 * 24 * 60 * 60; // 30天（秒）
    await cache.set(`blacklist_${token}`, true, tokenExpiry);
  }

  logger.info(`User logged out: ${req.user.email}`);

  res.json({
    success: true,
    message: 'Logout successful'
  });
});

// @desc    获取当前用户信息
// @route   GET /api/auth/me
// @access  Private
const getMe = asyncHandler(async (req, res) => {
  const user = await User.findById(req.user.id);

  if (!user) {
    res.status(404);
    throw new Error('User not found');
  }

  res.json({
    success: true,
    data: {
      user: user.toJSON()
    }
  });
});

// @desc    请求密码重置
// @route   POST /api/auth/forgot-password
// @access  Public
const forgotPassword = asyncHandler(async (req, res) => {
  const { email } = req.body;

  const user = await User.findByEmailWithPassword(email);

  if (!user) {
    // 为了安全，即使用户不存在也返回成功消息
    res.json({
      success: true,
      message: 'If the email exists, a password reset link has been sent'
    });
    return;
  }

  // 生成重置token
  const resetToken = crypto.randomBytes(32).toString('hex');
  const resetTokenExpiry = Date.now() + 10 * 60 * 1000; // 10分钟后过期

  // 存储重置token到Redis
  await cache.set(`password_reset_${resetToken}`, {
    userId: user.id,
    email: user.email,
    expiresAt: resetTokenExpiry
  }, 600); // 10分钟TTL

  // 这里应该发送邮件，暂时只记录日志
  logger.info(`Password reset requested for: ${email}, token: ${resetToken}`);

  res.json({
    success: true,
    message: 'If the email exists, a password reset link has been sent',
    // 开发环境下返回token（生产环境应该删除）
    ...(process.env.NODE_ENV === 'development' && { resetToken })
  });
});

// @desc    重置密码
// @route   POST /api/auth/reset-password
// @access  Public
const resetPassword = asyncHandler(async (req, res) => {
  const { token, password } = req.body;

  // 从Redis获取重置信息
  const resetInfo = await cache.get(`password_reset_${token}`);

  if (!resetInfo || resetInfo.expiresAt < Date.now()) {
    res.status(400);
    throw new Error('Invalid or expired reset token');
  }

  // 查找用户
  const user = await User.findById(resetInfo.userId);
  if (!user) {
    res.status(400);
    throw new Error('User not found');
  }

  // 更新密码（这里需要直接更新数据库，因为我们没有当前密码）
  const bcrypt = require('bcryptjs');
  const salt = await bcrypt.genSalt(10);
  const hashedPassword = await bcrypt.hash(password, salt);

  const { query } = require('../config/database');
  await query(
    'UPDATE users SET password = ?, updated_at = NOW() WHERE id = ?',
    [hashedPassword, user.id]
  );

  // 删除重置token
  await cache.del(`password_reset_${token}`);

  logger.info(`Password reset completed for user: ${user.email}`);

  res.json({
    success: true,
    message: 'Password reset successful'
  });
});

module.exports = {
  register,
  login,
  refreshToken,
  logout,
  getMe,
  forgotPassword,
  resetPassword
};